home *** CD-ROM | disk | FTP | other *** search
/ Fritz: All Fritz / All Fritz.zip / All Fritz / FILES / PROGBLER / WHIZZARD.LZH / ASMBASIC.ASM next >
Assembly Source File  |  1984-06-18  |  8KB  |  279 lines

  1. COMMENT *
  2.  
  3.                  CLUBware  (tm)
  4.  
  5.      ASMBASIC interfaces assembly language subroutines to the BASIC
  6.          interpreter.
  7.  
  8.            Copyright 1984 Rayhawk Automation N.W. Inc
  9.                   P.O. Box 1427
  10.                   Beaverton, Oregon   97075
  11.  
  12.  
  13.      Method:
  14.           1) Our Basic code calls the service routines directly
  15.            CALL QPRINT ( FLAG% , STRING )
  16.           2) The flag indicates whether we are interpreted or compiled
  17.           3) Compiled code has the object code for QPRINT linked into it
  18.           4) Interpreted code has a separate module resident below
  19.            the BASIC interpreter (this module contains QPRINT)
  20.           5) Both the interpreted Basic code and the compiled Basic code
  21.            use an initialization routine to determine whether
  22.            currently running compiled or interpreted and sets global
  23.            variable, FLAG, accordingly
  24.           6) If compiled, basic initialization routine does nothing
  25.           7) If interpreted, initialization routine performs following
  26.            steps
  27.            A) Insert two instruction assembly language subroutine
  28.             into variable SUBINIT
  29.             Two instructions are   INT 67h
  30.                            RET 2
  31.            B) Make the following assignments
  32.             SEGVALUE% = 0
  33.             QPRINT%   = 1
  34.             ZPRINT%   = 2
  35.             CLREOL%   = 3
  36.             SHELSORT% = 4
  37.             etc
  38.             (Everyone concerned with this project will agree on an
  39.               ordering and use it consistently.)
  40.            C) Make repeated calls to SUBINIT
  41.             CALL SUBINIT ( SEGVALUE% )
  42.             CALL SUBINIT ( QPRINT% )
  43.             CALL SUBINIT ( ZPRINT% )
  44.             CALL SUBINIT ( CLREOL% )
  45.             CALL SUBINIT ( SHELSORT% )
  46.            D) Use the Basic DEFSEG to make our subroutines addressable
  47.             DEFSEG = SEGVALUE%
  48.            E) Return from initialization
  49.            F) Implied but not stated is that after return from SUBINIT
  50.             the variable QPRINT% no longer contains 1 but the
  51.             offset within SEGVALUE% where the QPRINT% subroutine
  52.             can be found. Same for other subroutines
  53.                                           *
  54.  
  55.  
  56. CODE      SEGMENT PARA PUBLIC 'CODE'
  57.       ASSUME  CS:CODE,DS:NOTHING,ES:NOTHING,SS:STACK
  58.  
  59. ;_______________________________________________________________________________
  60.  
  61.  
  62. ;              | - - - - - - - - - - - - - - - - - - - - - - - - -|
  63. ;              |                          |
  64. ;              |        INT 67h    interrupt routine     |
  65. ;              |                          |
  66. ;              | - - - - - - - - - - - - - - - - - - - - - - - - -|
  67.  
  68.       EXTRN   QPRINT:FAR
  69.       EXTRN   SCRLDN:FAR
  70.       EXTRN   SCRLUP:FAR
  71.       EXTRN   XREP:FAR
  72.       EXTRN   YREP:FAR
  73.       EXTRN   CLREOL:FAR
  74.       EXTRN   CLREOS:FAR
  75.       EXTRN   ZPRINT:FAR
  76. ;      EXTRN   STDIN:FAR
  77. ;      EXTRN   STDOUT:FAR
  78.  
  79. TABLE_LEN      LABEL  WORD
  80.       DW      8               ; eight subroutines so far
  81.  
  82.       DW      5252h            ; tag to allow basic to make sure
  83.                        ;  ASMBASIC is resident
  84. ; entry point for assembly SUBINT routine
  85.  
  86. SUBINIT   PROC      FAR
  87.       JMP      SHORT SUB_CODE
  88.  
  89. SUBROUTINE_TABLE  LABEL  WORD           ; table of subroutine offsets
  90.       DW      OFFSET BAD_CALL      ; 0
  91.       DW      OFFSET QPRINT        ; 1
  92.       DW      OFFSET SCRLDN        ; 2
  93.       DW      OFFSET SCRLUP        ; 3
  94.       DW      OFFSET XREP           ; 4
  95.       DW      OFFSET YREP           ; 5
  96.       DW      OFFSET CLREOL        ; 6
  97.       DW      OFFSET CLREOS        ; 7
  98.       DW      OFFSET ZPRINT        ; 8
  99. ;      DW      OFFSET STDIN           ; 9
  100. ;      DW      OFFSET STDOUT        ; 10
  101.  
  102. ARG      EQU      WORD PTR [BP+12]     ; argument to SUBINIT
  103.  
  104. SUB_CODE:
  105.  
  106.       PUSH      BP               ; address the argument
  107.       MOV      BP,SP
  108.  
  109.       MOV      SI,ARG           ; load the address of the argument
  110.       MOV      AX,WORD PTR [SI]     ; load the argument itself
  111.  
  112.  
  113. ;    argument of 0 means return code segment for use in DEFSEG statement
  114.  
  115.       CMP      AX,0               ; return segment?
  116.       JA      PREP_SUB
  117.  
  118.       MOV      AX,SEG CODE           ; get our segment
  119.       MOV      WORD PTR DS:[SI],AX  ; return it to caller
  120.       JMP      FAR PTR SUBINIT_DONE
  121.  
  122. PREP_SUB:
  123.  
  124.  
  125. ;    non-zero argument means return offset of that subroutine
  126.  
  127.       CMP      AX,TABLE_LEN
  128.       JBE      GOOD_ARGUMENT
  129.  
  130.       CALL      FAR PTR BAD_CALL     ; let user know a bad call
  131.       MOV      AX,0               ;  has been made
  132.  
  133. GOOD_ARGUMENT:
  134.  
  135.       SHL      AX,1               ; each table entry is 2 bytes long
  136.       MOV      BX,AX
  137.       MOV      AX,SUBROUTINE_TABLE[BX]     ; load subroutine offset
  138.       MOV      WORD PTR DS:[SI],AX          ; return offset to caller
  139.  
  140.  
  141.  
  142. ;    initialization complete, return to caller
  143. ;      stack is cleared by code within basic segment
  144.  
  145. SUBINIT_DONE:
  146.       POP      BP
  147.       IRET
  148.  
  149. SUBINIT   ENDP
  150.  
  151. ;_______________________________________________________________________________
  152.  
  153. BAD_MESSAGE      LABEL  BYTE
  154.       DB      10,13,'An invalid subroutine call was made to subinit.',10,13
  155.       DB      'There are only 8 subroutines defined within subinit.',10,13
  156.       DB      'A request was made for a subroutine outside of this range.'
  157.       DB      10,13,'$'
  158.  
  159. BAD_CALL  PROC      FAR
  160.  
  161.       PUSH      DS
  162.  
  163.       MOV      AX,SEG CODE
  164.       MOV      DS,AX
  165.  
  166.       MOV      DX,OFFSET BAD_MESSAGE
  167.       MOV      AH,09
  168.       INT      21h
  169.  
  170.       POP      DS
  171.       RET
  172.  
  173. BAD_CALL  ENDP
  174.  
  175. ;_______________________________________________________________________________
  176.  
  177.  
  178. ASMBASIC  PROC      FAR
  179.  
  180. ;                     Establish standard DOS linkage
  181.       PUSH      DS               ; Push addr of Program Segment Prefix
  182.       XOR      AX,AX            ; Zero AX
  183.       PUSH      AX               ; Push zero onto stack
  184. ;                     (offset of INT 20 within PSF)
  185.  
  186.  
  187. ;              | - - - - - - - - - - - - - - - - - - - - - - - - -|
  188. ;              |                          |
  189. ;              |        take over the INT 67h         |
  190. ;              |        interrupt if not already done     |
  191. ;              |                          |
  192. ;              | - - - - - - - - - - - - - - - - - - - - - - - - -|
  193.  
  194.       MOV      DS,AX            ; address low memory
  195.       LDS      BX,DWORD PTR DS:[019Ch]  ; load interrupt vector for int 67
  196.  
  197.       MOV      AX,WORD PTR SUBINIT
  198.       CMP      AX,WORD PTR DS:[BX]
  199.       JNE      NOT_HERE_YET
  200.       MOV      AX,WORD PTR SUBINIT+2
  201.       CMP      AX,WORD PTR DS:[BX+2]
  202.       JNE      NOT_HERE_YET
  203.       MOV      AX,WORD PTR SUBINIT+4
  204.       CMP      AX,WORD PTR DS:[BX+4]
  205.       JNE      NOT_HERE_YET
  206.       MOV      AX,WORD PTR SUBINIT+6
  207.       CMP      AX,WORD PTR DS:[BX+6]
  208.       JNE      NOT_HERE_YET
  209.  
  210.       JMP      SHORT ALREADY_RESIDENT
  211.  
  212. NOT_HERE_YET:
  213.  
  214.       MOV      AX,SEG ASMBASIC      ; Move our code segment
  215.       MOV      DS,AX            ; to the data segment register
  216.  
  217. ;              | - - - - - - - - - - - - - - - - - - - - - - - - -|
  218. ;              |                          |
  219. ;              |        take over the INT 67h         |
  220. ;              |        interrupt                 |
  221. ;              |                          |
  222. ;              | - - - - - - - - - - - - - - - - - - - - - - - - -|
  223.  
  224.       MOV      DX,OFFSET SUBINIT    ; Load offset of interrupt service mod
  225.       MOV      AX,2567h           ; Prepare for DOS service call type 25
  226. ;                     to establish service for INT 05
  227.       INT      21h               ; Ask DOS to establish service
  228.  
  229. ;              | - - - - - - - - - - - - - - - - - - - - - - - - -|
  230. ;              |                          |
  231. ;              |        modify INT 20 into INT 27 in the     |
  232. ;              |        program segment prefix         |
  233. ;              |                          |
  234. ;              | - - - - - - - - - - - - - - - - - - - - - - - - -|
  235.  
  236.       MOV      BYTE PTR ES:[01],27h ; Change INT 20h to INT 27h
  237.  
  238. ;              | - - - - - - - - - - - - - - - - - - - - - - - - -|
  239. ;              |                          |
  240. ;              |     6) load address of ending tag into DX     |
  241. ;              |                          |
  242. ;              | - - - - - - - - - - - - - - - - - - - - - - - - -|
  243.  
  244.       MOV      AX,SEG BOTSTACK
  245.       SUB      AX,SEG ASMBASIC
  246.       MOV      CL,4               ; prepare for 4 bit shift
  247.       SHL      AX,CL            ; shift up (convert from seg to abs)
  248.       ADD      AX,OFFSET BOTSTACK   ; add address of bottom location
  249.       ADD      AX,0103h           ; Pad offset because DOS measures
  250. ;                      offset relative to Program
  251. ;                      Segment Prefix
  252.       MOV      DX,AX            ; leave where DOS will find it
  253.  
  254. ;              | - - - - - - - - - - - - - - - - - - - - - - - - -|
  255. ;              |                          |
  256. ;              |     7) use RET FAR to return to DOS and     |
  257. ;              |        leave service routine resident     |
  258. ;              |                          |
  259. ;              | - - - - - - - - - - - - - - - - - - - - - - - - -|
  260.  
  261.  
  262. ALREADY_RESIDENT:
  263.  
  264.       RET
  265.  
  266. ASMBASIC  ENDP
  267.  
  268. CODE      ENDS
  269.  
  270. ;_______________________________________________________________________________
  271.  
  272. STACK      SEGMENT PARA STACK 'STACK'
  273. BOTSTACK  LABEL   BYTE
  274.       DB      24 DUP('STACK***')
  275. TOPSTACK  DB      0
  276. STACK      ENDS
  277.  
  278.       END      ASMBASIC
  279.